package com.ericsson.epc.modules.trace.task;

import com.ericsson.common.mapper.JsonMapper;
import com.ericsson.common.pojo.FTPInfoVO;
import com.ericsson.common.quartz.task.ManualTask;
import com.ericsson.common.util.*;
import com.ericsson.epc.modules.sys.entity.EPCNetElement;
import com.ericsson.epc.modules.sys.entity.EpcDic;
import com.ericsson.epc.modules.sys.service.EPCNetElementService;
import com.ericsson.epc.modules.sys.service.EpcDicService;
import com.ericsson.epc.modules.trace.entity.*;
import com.ericsson.epc.modules.trace.service.SignalFileHistoryService;
import com.ericsson.epc.modules.trace.service.SignalFileService;
import com.ericsson.epc.modules.userebm.thread.MultiThread;
import com.fasterxml.jackson.databind.JavaType;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import lombok.Data;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author zhuguangrui
 */
@Component
public class SignallingTraceTask_OLD implements ManualTask {

    private final Logger log = LoggerUtils.Logger(LogFileName.SignallingTraceJob);

    @Autowired
    private EpcDicService epcDicService;
    @Autowired
    private EPCNetElementService epcNetElementService;
    @Autowired
    private SignalFileService signalFileService;
    @Autowired
    private SignalFileHistoryService signalFileHistoryService;

    @Value("${collectorIp}")
    private String collectorIp;

    @Override
    public void execute() {
        int currentHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        if(currentHour == 0) {
            currentHour = 24;
        }
        String retentionDays = epcDicService.selectEpcDic(new EpcDic("dataRetentionDays")).getValue();
        Calendar calendar = Calendar.getInstance();
        //设置需删除的日期标志
        calendar.set(Calendar.DAY_OF_YEAR,calendar.get(Calendar.DAY_OF_YEAR) - Integer.parseInt(retentionDays));
        String dayFlag = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
        deleteExpiredDir(dayFlag);
        List<SignalFile> allSignalFile = signalFileService.findList(null);
        if(allSignalFile != null && allSignalFile.size() > 0) {
            for(SignalFile signalFile : allSignalFile) {
                //删除mysql过期的数据
                signalFileHistoryService.deleteExpiredData(signalFile.getId(),dayFlag);

            }
        }
        String timeFlag = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(calendar.getTime());
        signalFileService.deleteExpiredData(timeFlag);

        log.info("==============SignallingTraceTask start================hour" + currentHour);
        long start = System.currentTimeMillis();
        String maxLength = epcDicService.selectEpcDic(new EpcDic("pcapMaxLength")).getValue();

        SignalFile tignalFile = new SignalFile();
        tignalFile.setStatus("1");
        List<SignalFile> signalFileList = signalFileService.findList(tignalFile);
        if (signalFileList != null && signalFileList.size() > 0) {
            String datePath = DateUtils.getStatisTime(60,new Date(),"yyyy-MM-dd");
            PoolNetInfo mmeList = new PoolNetInfo();
            PoolNetInfo saegwList = new PoolNetInfo();
            PoolNetInfo pcrfList = new PoolNetInfo();
            //拼接imsi参数
            StringBuffer imsiBuffer = new StringBuffer();
            //拼接msisdn参数
            StringBuffer msisdnBuffer = new StringBuffer();
            //拼接dest_folder参数
            StringBuffer destFolderBuffer = new StringBuffer();
            Map<String, Map<String, NodeInfo>> nodeInfoMap = new HashMap<>();
            for (SignalFile signalFileItem : signalFileList) {
                //判断当前号码的抓包时长是否达到至少15分钟
                if (!durationMinute(signalFileItem.getStarttime()) || signalFileItem.getNettype().contains("USERFACE")) {
                    continue;
                }
                imsiBuffer.append(" ").append(signalFileItem.getImsi());
                msisdnBuffer.append(" ").append(signalFileItem.getMsisdn());
                destFolderBuffer.append(" ").append("/opt/Ericsson/core/signal/files/" + signalFileItem.getId() + "/" + datePath+"/"+currentHour);
                File file = new File("/opt/Ericsson/core/signal/files/" + signalFileItem.getId() + "/" + datePath+"/"+currentHour);
                if (!file.exists()) {
                    file.mkdirs();
                }
                //开始准备json文件
                UserSignalInfoEntity userSignalInfo = null;
                try {
                    JavaType javaType = JsonMapper.getInstance().getTypeFactory().constructType(UserSignalInfoEntity.class);
                    userSignalInfo = JsonMapper.getInstance().readValue(signalFileItem.getJsontext(), javaType);
                    PoolNetInfo mmePool = userSignalInfo.getMmePool();
                    PoolNetInfo saegwPool = userSignalInfo.getSaegwPool();
                    PoolNetInfo pcrfPool = userSignalInfo.getPcrfPool();
                    loadNetList(mmeList, mmePool);
                    loadNetList(saegwList, saegwPool);
                    loadNetList(pcrfList, pcrfPool);
                    if (userSignalInfo.getNetType() != null && userSignalInfo.getNetType().contains("PCRF")) {
                        nodeInfoMap.put("pcrf", genNodeInfo(pcrfList,"pcrf"));
                    }
                    if (userSignalInfo.getNetType() != null && userSignalInfo.getNetType().contains("USERFACE")) {
                        EPCNetElement newnetelement = epcNetElementService.findByName(userSignalInfo.getSaegwNetName());
                        nodeInfoMap.put("userface", genNodeInfo(newnetelement));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            nodeInfoMap.put("mme", genNodeInfo(mmeList,"mme"));
            nodeInfoMap.put("epg", genNodeInfo(saegwList,"epg"));
            File fileTxt = new File("/opt/Ericsson/core/signal/files/cron/node_info.json");
            try {
                if (!fileTxt.exists()) {
                    fileTxt.getParentFile().mkdirs();
                    fileTxt.createNewFile();
                } else {
                    fileTxt.delete();
                    fileTxt.createNewFile();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            long pcapCmdStart = System.currentTimeMillis();
            List<String> pcapPaths = executeMultiPcap(nodeInfoMap,imsiBuffer.toString(), msisdnBuffer.toString(), destFolderBuffer.toString());
            log.info("===== download_parse_uetrace_files.py hour :" +currentHour+ " use :" + (System.currentTimeMillis() - pcapCmdStart) / 60000 + "min");
            //更新pcap包至历史表
            Map<String,Boolean> needUpdateMap = new HashMap<>();
            for (SignalFile signalFileItem : signalFileList) {
                for (String pcapPath : pcapPaths) {
                    if (pcapPath.contains(signalFileItem.getImsi())) {
                        File pcapFile = new File(pcapPath);
                        if (pcapFile.exists() && pcapFile.isFile()) {
                            //此情况为特殊情况，当定时任务已经开启暂未执行完时，用户在页面点击停止抓包，用户点击的抓包会比定时任务提前完成。
                            SignalFileHistory signalFileHistory = queryHistoryOne(signalFileItem.getId(), datePath, currentHour);
                            if(signalFileHistory == null) {
                                needUpdateMap.put(signalFileItem.getId(),true);
                                //当前日期，当前小时的pcap文件入库
                                saveSignalFileHistory(signalFileItem.getId(), pcapPath, null, null, datePath, currentHour, FileSizeHelper.getHumanReadableFileSize(pcapFile.length()));
                            }else{
                                needUpdateMap.put(signalFileItem.getId(),false);
                            }
                        }
                        //删除中间过程产生的临时文件
                        deleteExpiredFiles(pcapPath);
                    }
                }
            }
            long genChartCmdStart = System.currentTimeMillis();
            String cmdParams = epcDicService.selectEpcDic(new EpcDic("filterGenChartParam")).getValue();
            //生成流程图
            for (SignalFile signalFileItem : signalFileList) {
                for (String pcapPath : pcapPaths) {
                    if (pcapPath.contains(signalFileItem.getImsi())) {
                        File pcapFile = new File(pcapPath);
                        if (pcapFile.exists() && pcapFile.isFile() && pcapFile.length() < 1024 * 1024 * Long.valueOf(maxLength)) {
                           //保证pcap包与流程图是匹配的
                            if(needUpdateMap.get(signalFileItem.getId())) {
                                long execChartStart = System.currentTimeMillis();
                               String htmlPath = executeFlowChart(pcapPath, signalFileItem.getMsisdn(), signalFileItem.getId(), datePath,currentHour,cmdParams);
                               //ebm信令聚合追踪流程图
                               //String ebmHtmlPath = executeEbmFlowChart(pcapPath,signalFileItem.getMsisdn(), Jdk8DateUtils.yesterday().formatDateTime("yyyyMMdd000000"),Jdk8DateUtils.yesterday().formatDateTime("yyyyMMdd235959"),null,Global.getConfig("signal.ebm.static.resources"),signalFileItem.getId(),datePath);
                               SignalFileHistory signalFileHistory = queryHistoryOne(signalFileItem.getId(), datePath, currentHour);

                               if (signalFileHistory != null && StringUtils.isNotBlank(htmlPath)) {
                                   File htmlFile = new File(htmlPath);
                                   if (htmlFile.exists() && htmlFile.isFile()) {
                                       signalFileHistory.setHtmlsize(FileSizeHelper.getHumanReadableFileSize(htmlFile.length()));
                                   }
                                   signalFileHistory.setHtmlusetime((System.currentTimeMillis() - execChartStart) / 1000);
                                   signalFileHistory.setHtmlpath(htmlPath);
                                   signalFileHistoryService.update(signalFileHistory);
                               }
                           }
                        } else {
                            log.info(pcapPath + "过大或文件不存在，不进行处理 hour:" +currentHour+ "文件大小为：" + FileSizeHelper.getHumanReadableFileSize(pcapFile.length()));
                        }
                    }
                }
            }
            log.info("==== filter_genchart.pl hour :" +currentHour+ "use :" + (System.currentTimeMillis() - genChartCmdStart) / 60000 + "min");
        }
        log.info("==============SignallingTraceTask hour :" +currentHour+ "=====end  all finish use :" + (System.currentTimeMillis() - start) / 60000 + "min");
    }


    private void deleteExpiredDir(String dayFlag) {
        File rootPath = new File("/opt/Ericsson/core/signal/files/");
        if (rootPath.exists() && rootPath.isDirectory()) {
            File[] fileIdPath = rootPath.listFiles();
            for (File idPath : fileIdPath) {
                if(idPath.exists() && idPath.isDirectory()) {
                    File[] fileDatePath = idPath.listFiles();
                    for(File datePath : fileDatePath) {
                        //清除过期的文件目录
                        if(datePath.isDirectory() && datePath.getName().compareTo(dayFlag) < 0){
                            FileUtil.deleteDir(datePath);
                            log.info("delete Expired path is : "+datePath);
                        }
                    }
                    File[] subFiles = idPath.listFiles();
                    if(subFiles == null || subFiles.length == 0 || (subFiles.length == 1 && subFiles[0].isFile())) {
                        FileUtil.deleteDir(idPath);
                    }
                }
            }
        }
    }

    /**
     * 判断抓包时长是否达到15分钟以上
     *
     * @param startTime
     * @return
     */
    private static boolean durationMinute(String startTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return (System.currentTimeMillis() - sdf.parse(startTime).getTime()) >= 60 * 15 * 1000;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 拼装池组信息
     *
     * @param netList
     * @param poolNetInfo
     */
    private static void loadNetList(PoolNetInfo netList, PoolNetInfo poolNetInfo) {
        for (int i = 0; i < poolNetInfo.getNetNames().size(); i++) {
            if (!netList.getNetNames().contains(poolNetInfo.getNetNames().get(i))) {
                netList.getNetNames().add(poolNetInfo.getNetNames().get(i));
                netList.getNetIps().add(poolNetInfo.getNetIps().get(i));
                if (StringUtils.isEmpty(netList.getUsername())) {
                    netList.setUsername(poolNetInfo.getUsername());
                }
                if (StringUtils.isEmpty(netList.getPassword())) {
                    netList.setPassword(poolNetInfo.getPassword());
                }
            }
        }
    }

    /**
     * 为json文件准备节点信息
     *
     * @param poolInfo 池组信息
     * @return
     */
    private static Map<String, NodeInfo> genNodeInfo(PoolNetInfo poolInfo,String netType) {
        Map<String, NodeInfo> nodeInfoMap = new HashMap<>();
        if (poolInfo.getNetNames().size() > 0) {
            for (int i = 0; i < poolInfo.getNetNames().size(); i++) {
                NodeInfo nodeItem = new NodeInfo();
                nodeItem.setHost(poolInfo.getNetIps().get(i));
                nodeItem.setUsername(poolInfo.getUsername());
                nodeItem.setPassword(poolInfo.getPassword());
                nodeItem.setNetType(netType);
                nodeItem.setNetName(poolInfo.getNetNames().get(i));
                nodeInfoMap.put(poolInfo.getNetNames().get(i), nodeItem);
            }
        }
        return nodeInfoMap;
    }

    /**
     * 为json文件准备节点信息
     *
     * @param epcNetElement 网元信息
     * @return
     */
    private static Map<String, NodeInfo> genNodeInfo(EPCNetElement epcNetElement) {
        Map<String, NodeInfo> nodeInfoMap = new HashMap<>();
        if (epcNetElement != null) {
            NodeInfo nodeItem = new NodeInfo();
            nodeItem.setHost(epcNetElement.getIpadr());
            nodeItem.setUsername(epcNetElement.getUsername1());
            nodeItem.setPassword(epcNetElement.getPassword1());
            nodeInfoMap.put(epcNetElement.getFname(), nodeItem);
        }
        return nodeInfoMap;
    }


    /**
     * 执行批量号码抓包文件下载脚本
     *
     * @param imsi
     * @param msisdn
     * @param descFolder
     * @return
     */
    private List<String> executeMultiPcap(Map<String, Map<String, NodeInfo>> nodeInfoMap,String imsi, String msisdn, String descFolder) {
        List<String> pcapNames = new ArrayList<>();
        List<Map<String, NodeInfo>> netTypeList=new ArrayList<>();
        for(Map<String, NodeInfo> value : nodeInfoMap.values()){
            netTypeList.add(value);
        }
        long now=System.currentTimeMillis();
        String localDir="/opt/Ericsson/core/signal/files/tmp/"+now+File.separator;
        String imsiStr[]=imsi.trim().split(" ");
        String msisdnStr[]=msisdn.trim().split(" ");
        String descFolderStr[]=descFolder.trim().split(" ");
        log.info("downloadAndPerl start");
        MultiThread<Map<String, NodeInfo>,List<String>> netTypeMultiThread=new MultiThread<Map<String, NodeInfo>, List<String>>(netTypeList) {
            @Override
            public Map<String, Set<String>> outExecute(int currentThread, Map<String, NodeInfo> data) {
                List<NodeInfo> nodeInfos=data.entrySet().stream().map(e -> e.getValue()).collect(Collectors.toList());
                dealSingleNet(nodeInfos, imsiStr, msisdnStr, descFolderStr,localDir);
                return null;
            }
        };
        try {
            netTypeMultiThread.getResult();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        log.info("downloadAndPerl stop");
        log.info("merageAndAnalysisPacp start");
        //合包及解包
        pcapNames=merageAndAnalysisPacp(imsiStr,now,descFolderStr);
        log.info("merageAndAnalysisPacp stop pcapNames size:"+pcapNames.size());
        //删除临时目录
        try {
            FileUtils.cleanDirectory(new File(localDir));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pcapNames;
    }

    public static void main(String[] args) {
        System.out.println(9%10);
        System.out.println(9/10);
    }

    public List<List<SingleObject>> dealMerageAndSharkData(List<SingleObject> singleObjects) {
        int threadSize = 10;//每10条数据开启一个线程
        int remainder = singleObjects.size()%threadSize;
        int threadNum  = 0;//线程数
        if(remainder == 0){
            threadNum  = singleObjects.size()/threadSize;
        } else {
            threadNum  = singleObjects.size()/threadSize + 1;
        }
        List<SingleObject> sList = null;
        List<List<SingleObject>> total=new ArrayList<>();
        for(int i=0;i<threadNum;i++){
            if(i == threadNum - 1){
                sList = singleObjects.subList(i*threadSize, singleObjects.size());
                total.add(sList);
            } else {
                sList = singleObjects.subList(i*threadSize, (i+1)*threadSize);
                total.add(sList);
            }
        }
        return total;
    }

    /**
     * 合包及解包
     * @param imsiStr
     * @param now
     * @param descFolderStr
     */
    private List<String> merageAndAnalysisPacp(String imsiStr[],long now,String descFolderStr[]){
        List<SingleObject> singleObjects=new ArrayList<>();
        List<List<SingleObject>> threadAndData=new ArrayList<>();
        SingleObject singleObject;
        for(int n=0;n<imsiStr.length;n++){
            singleObject=new SingleObject();
            singleObject.setImsi(imsiStr[n]);
            singleObject.setDest(descFolderStr[n]);
            singleObjects.add(singleObject);
        }

        threadAndData= dealMerageAndSharkData(singleObjects);

        String rootname=epcDicService.selectEpcDic(new EpcDic("SYSUSER")).getValue();
        String rootpwd=epcDicService.selectEpcDic(new EpcDic("SYSPWD")).getValue();
        String capturename=epcDicService.selectEpcDic(new EpcDic("CAPTUREUSER")).getValue();
        String capturepwd=epcDicService.selectEpcDic(new EpcDic("CAPTUREPWD")).getValue();

        MultiThread<List<SingleObject>,List<String>> merageAndShark=new MultiThread<List<SingleObject>, List<String>>(threadAndData) {
            @Override
            public Map<String, Set<String>> outExecute(int currentThread, List<SingleObject> data) {
                Map<String,Set<String>> imsiAndPath=new HashMap<>();
                for(SingleObject singleObject1:data){
                    log.info(singleObject1.getImsi()+"mergeCap start");
                    //合包
                    mergeCap(singleObject1,now);
                    log.info(singleObject1.getImsi()+"mergeCap stop");
                    //tshark 解包
                    log.info(singleObject1.getImsi()+"analysisCap start");
                    imsiAndPath.put(singleObject1.getImsi(),analysisCap(singleObject1,now,rootname,rootpwd,capturename,capturepwd));
                    log.info(singleObject1.getImsi()+"analysisCap stop");
                }
                return imsiAndPath;
            }
        };

        List<Map<String,Set<String>>> result=null;
        try {
            result=merageAndShark.getResult();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        List<String> paramList=new ArrayList<>();
        if(null!=result){
            for(Map<String,Set<String>> temp:result) {
                Iterator<Map.Entry<String, Set<String>>> it = temp.entrySet().iterator();
                while (it.hasNext()) {
                    Map.Entry<String, Set<String>> entry = it.next();
                    paramList.addAll(entry.getValue());
                }
            }
        }
        return paramList;
    }

    /**
     * 解包
     * @param singleObject
     * @param now
     * @return
     */
    private Set<String> analysisCap(SingleObject singleObject, long now,String rootname,String rootpwd,String capturename,String capturepwd) {
        Set<String> filePath=new HashSet<>();
        //-----------------------------------------------------------------------
        String regex=".*?"+singleObject.getImsi()+".withdup.pcap";
        File[] fileImsi=listFilesMatching(new File(singleObject.getDest()),regex);
        if(fileImsi.length>0) {
            SSHUtil sshUtilMod=null;
            try {
                sshUtilMod = new SSHUtil(collectorIp, rootname, rootpwd);
                sshUtilMod.connect();
                sshUtilMod.getShellChannel();
                sshUtilMod.execCommand("chmod -R 777 /opt/Ericsson/core/signal/files/");
            }catch (Exception ex){
                log.error("analysisCap 470"+ex.getMessage());
            }
            finally{
                if(null!=sshUtilMod) {
                    sshUtilMod.disconnect();
                }
            }
            //---------------------------------------------------------------------------------------------------
            String cmdAnalysisCap= "/usr/bin/tshark -q -Xlua_script:/opt/Ericsson/core/bin/single/wnaa_dup.lua " +
                    " -R frame -2 -Y \"not wnaa_dup.dup_flag\"" +
                    " -r " + singleObject.getDest() + File.separator + fileImsi[0].getName() +
                    " -w " + singleObject.getDest() + File.separator + fileImsi[0].getName().replace(".withdup.pcap","") + ".unsorted.pcap";
            SSHUtil sshUtil=null;
            try {
                sshUtil = new SSHUtil(collectorIp, capturename, capturepwd);
                sshUtil.connect();
                sshUtil.getShellChannel();
                sshUtil.execCommand(cmdAnalysisCap);
            }catch (Exception ex){
                log.error("analysisCap 489"+ex.getMessage(),ex);
            }
            finally{
                if(null!=sshUtil) {
                    sshUtil.disconnect();
                }
            }
        }
        //排序
        //-----------------------------------------------------------------------
        String regexSort=".*?"+singleObject.getImsi()+".unsorted.pcap";
        File[] fileImsiSort=listFilesMatching(new File(singleObject.getDest()),regexSort);
        if(fileImsiSort.length>0){
            Process procSortCap;
            String[] cmdSortCap = new String[3];
            cmdSortCap[0] = "sh";
            cmdSortCap[1] = "-c";
            cmdSortCap[2] = "/usr/local/bin/reordercap  " +
                    singleObject.getDest()+File.separator + fileImsiSort[0].getName() + "  "+
                    singleObject.getDest()+File.separator  +fileImsiSort[0].getName().replace(".unsorted.pcap","") + ".pcap";
            log.info(cmdSortCap[2]);
            try {
                Runtime rt=Runtime.getRuntime();
                procSortCap = rt.exec(cmdSortCap);
                BufferedReader brSortCap = new BufferedReader(new InputStreamReader(procSortCap.getInputStream()));
                String lineMergeCap;
                while ((lineMergeCap = brSortCap.readLine()) != null) {
                    if (lineMergeCap.trim().endsWith("#")) {
                        break;
                    }
                }
                brSortCap.close();
                procSortCap.waitFor();
                procSortCap.destroy();
            } catch (InterruptedException e) {
                log.error("524"+e.getMessage());
            } catch (IOException e) {
                log.error("526"+e.getMessage());
            }
            filePath.add(singleObject.getDest() +File.separator +fileImsiSort[0].getName().replace(".unsorted.pcap","") + ".pcap");
        }
        System.out.println(filePath);
        return filePath;
    }

    /**
     * 合包
     * @param singleObject
     */
    private void mergeCap(SingleObject singleObject,long now){
            String regex=".*?"+singleObject.getImsi()+".pcap";
            File[] fileImsi=listFilesMatching(new File(singleObject.getDest()),regex);
            if(fileImsi.length>0){
                Process procMergeCap;
                String[] cmdMergeCap = new String[3];
                cmdMergeCap[0] = "sh";
                cmdMergeCap[1] = "-c";
                cmdMergeCap[2] = "/usr/bin/mergecap -w " +
                        singleObject.getDest() +File.separator+ now + '-' + singleObject.getImsi() + ".withdup.pcap  "+
                        singleObject.getDest()  + "/*"+ singleObject.getImsi() + ".pcap";
                log.info(cmdMergeCap[2]);
                try {
                    procMergeCap = Runtime.getRuntime().exec(cmdMergeCap);
                    BufferedReader brMergeCap = new BufferedReader(new InputStreamReader(procMergeCap.getInputStream()));
                    String lineMergeCap;
                    while ((lineMergeCap = brMergeCap.readLine()) != null) {
                        if (lineMergeCap.trim().endsWith("#")) {
                            break;
                        }
                    }
                    brMergeCap.close();
                    procMergeCap.waitFor();
                    procMergeCap.destroy();
                } catch (InterruptedException e) {
                    log.error("563"+e.getMessage());
                } catch (IOException e) {
                    log.error("565"+e.getMessage());
                }
            }
    }

    /**
     * 处理批量下载等操作
     */
    private void dealSingleNet(List<NodeInfo> nodeInfoList,String imsiStr[], String msisdnStr[], String descFolderStr[],String local){
        MultiThread<NodeInfo, Map<String,Set<String>>> multiThreadFile = new MultiThread<NodeInfo,Map<String,Set<String>>>(nodeInfoList){
            @Override
            public Map<String, Set<String>> outExecute(int currentThread, NodeInfo data) {
                try {
                    List<File> files=downloadSingle(data,local);
                    if(files.size()>0) {
                        log.info(data.getNetName()+"deal start");
                        if (data.getNetType().equals("mme")) {
                            dealMMEFile(data, files, imsiStr, msisdnStr, descFolderStr, local);
                        } else {
                            dealSAEGWFile(data, files, imsiStr, msisdnStr, descFolderStr, local);
                        }
                        log.info(data.getNetName()+"deal stop");
                    }
                } catch (Exception e) {
                    log.error("589"+e.getMessage());
                }
                return null;
            }
        };
        try {
            //每台话单采集器的数据
            multiThreadFile.getResult();
        }catch (Exception ex){
            log.error("get single data error"+ex.getMessage());
        }
    }

    private void dealSAEGWFile(NodeInfo data, List<File> files,String imsiStr[], String msisdnStr[], String descFolderStr[], String local) {
        //----------------------------------------------------------------------------------------
        log.info(data.getNetName()+"dealSAEGWFile cat start");
        Process procCat;
        String[] cmd = new String[3];
        cmd[0] = "sh";
        cmd[1] = "-c";
        cmd[2] = "/usr/bin/cat " +local+data.getNetName()+File.separator+"*"+
                " > " +local+data.getNetName()+File.separator+data.getNetName();
        log.info(cmd[2]);
        try {
            procCat = Runtime.getRuntime().exec(cmd);
            BufferedReader brCat = new BufferedReader(new InputStreamReader(procCat.getInputStream()));
            String lineCat;
            while ((lineCat = brCat.readLine()) != null) {
                if (lineCat.trim().endsWith("#")) {
                    break;
                }
            }
            brCat.close();
            procCat.waitFor();
            procCat.destroy();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info(data.getNetName()+"dealSAEGWFile cat stop");
        //-------------------------------------------------------------------------------------------
        log.info(data.getNetName()+"dealSAEGWFile epg_uetrace2pcap.pl start");
        Process procPerl;
        String[] cmdPerl = new String[3];
        cmdPerl[0] = "sh";
        cmdPerl[1] = "-c";
        cmdPerl[2] = "perl /opt/Ericsson/core/bin/single/epg_uetrace2pcap.pl " +
                " -f " +local+data.getNetName()+File.separator+data.getNetName()+
                " -o " +local+data.getNetName()+File.separator+
                " -p ";
        log.info(cmd[2]);
        try {
            procPerl = Runtime.getRuntime().exec(cmdPerl);
            BufferedReader brPerl = new BufferedReader(new InputStreamReader(procPerl.getInputStream()));
            String line;
            while ((line = brPerl.readLine()) != null) {
                if (line.trim().endsWith("#")) {
                    break;
                }
            }
            brPerl.close();
            procPerl.waitFor();
            procPerl.destroy();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info(data.getNetName()+"dealSAEGWFile epg_uetrace2pcap.pl stop");
        //-----------------------------------------------------------------------------------------------------
        log.info(data.getNetName()+"dealSAEGWFile mv start");
        for(int i=0;i<imsiStr.length;i++){
            String regex=".*?"+imsiStr[i]+".pcap";
            File[] fileImsi=listFilesMatching(new File(local+data.getNetName()+File.separator),regex);
            if(fileImsi.length>0){
                Process procMv;
                String[] cmdMv = new String[3];
                cmdMv[0] = "sh";
                cmdMv[1] = "-c";
                cmdMv[2] = "/usr/bin/mv "
                        +fileImsi[0]+
                        " " +descFolderStr[i]+File.separator+ data.getNetName() + "-" + i + "-" +imsiStr[i] + ".pcap";
                log.info(cmd[2]);
                try {
                    procMv = Runtime.getRuntime().exec(cmdMv);
                    BufferedReader brMv = new BufferedReader(new InputStreamReader(procMv.getInputStream()));
                    String lineMv;
                    while ((lineMv = brMv.readLine()) != null) {
                        if (lineMv.trim().endsWith("#")) {
                            break;
                        }
                    }
                    brMv.close();
                    procMv.waitFor();
                    procMv.destroy();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        log.info(data.getNetName()+"dealSAEGWFile mv stop");
    }

    private void dealMMEFile(NodeInfo data, List<File> files, String imsiStr[], String msisdnStr[], String descFolderStr[], String local) {
        //-----------------------------------------------------------------------------------
        log.info(data.getNetName()+"dealMMEFile uetrace2pcap.pl start");
        Process proc;
        String[] cmd = new String[3];
        cmd[0] = "sh";
        cmd[1] = "-c";
        cmd[2] = "perl /opt/Ericsson/core/bin/single/uetrace2pcap.pl " +
                " -d " +local+data.getNetName()+File.separator+
                " -o " +local+data.getNetName()+File.separator;
        log.info(cmd[2]);
        try {
            proc = Runtime.getRuntime().exec(cmd);
            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                if (line.trim().endsWith("#")) {
                    break;
                }
            }
            br.close();
            proc.waitFor();
            proc.destroy();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info(data.getNetName()+"dealMMEFile uetrace2pcap.pl stop");
        //---------------------------------------------------------------------------------------------------
        log.info(data.getNetName()+"dealMMEFile replace3003.pl start");
        for(int i=0;i<imsiStr.length;i++){
            String regex=".*?"+imsiStr[i]+".pcap";
            File[] fileImsi=listFilesMatching(new File(local+data.getNetName()+File.separator),regex);
            if(fileImsi.length>0){
                Process proc3003;
                String[] cmd3003 = new String[3];
                cmd3003[0] = "sh";
                cmd3003[1] = "-c";
                cmd3003[2] = "perl /opt/Ericsson/core/bin/single/replace3003.pl "
                        +fileImsi[0]+
                        " " +descFolderStr[i]+File.separator+ data.getNetName() + "-" + i + "-" +imsiStr[i] + ".pcap" + ' ' +
                        data.getHost()+" ";
                log.info(cmd3003[2]);
                try {
                    proc3003 = Runtime.getRuntime().exec(cmd3003);
                    BufferedReader br3003 = new BufferedReader(new InputStreamReader(proc3003.getInputStream()));
                    String line3003;
                    while ((line3003 = br3003.readLine()) != null) {
                        if (line3003.trim().endsWith("#")) {
                            break;
                        }
                    }
                    br3003.close();
                    proc3003.waitFor();
                    proc3003.destroy();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        log.info(data.getNetName()+"dealMMEFile replace3003.pl stop");
    }

    private File[] listFilesMatching(File root, String regex) {
        if(!root.isDirectory()) {
            throw new IllegalArgumentException(root+" is no directory.");
        }
        final Pattern p = Pattern.compile(regex);
        return root.listFiles(new FileFilter(){
            @Override
            public boolean accept(File file) {
                return p.matcher(file.getName()).matches();
            }
        });

    }

    /**
     * 从网元下载信令追踪的抓包文件
     * @param nodeInfo
     * @param localDir
     * @return
     * @throws Exception
     */
    private List<File> downloadSingle(NodeInfo nodeInfo, String localDir) throws Exception {
            String beginTime = "B"+DateUtils.getStatisTime(60,new Date(),"yyyyMMdd.HH");
            FTPInfoVO ftpInfo = new FTPInfoVO();
            ftpInfo.setHost(nodeInfo.getHost());
            ftpInfo.setUserName(nodeInfo.getUsername());
            ftpInfo.setPassword(nodeInfo.getPassword());
            if(nodeInfo.getNetType().equals("mme")) {
                ftpInfo.setPath("/logs/ue_trace/ready/");
            }else{
                ftpInfo.setPath("/var/log/services/epg/uetrace/");
            }
            ftpInfo.setPort(21);
            localDir=localDir+nodeInfo.getNetName()+File.separator;
            List<File> fileList = new ArrayList<File>();
            SFtpCarrierUtil sftpCarrier = new SFtpCarrierUtil(ftpInfo, log);
            try {
                sftpCarrier.connect();
                Vector v = sftpCarrier.listFiles(ftpInfo.getPath());
                if (v.size() > 0) {
                    Iterator it = v.iterator();
                    while (it.hasNext()) {
                        ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) it.next();
                        String filename = entry.getFilename();
                        SftpATTRS attrs = entry.getAttrs();
                        if (!attrs.isDir()) {
                            if (filename.length() > 14 && filename.contains(beginTime)) {
                                File tempFile=sftpCarrier.downloadFileSingle(ftpInfo.getPath(), filename, localDir, filename);
                                if(null!=tempFile) {
                                    fileList.add(tempFile);
                                }
                            }
                        }
                    }
                }
            } catch (SftpException e) {
                e.printStackTrace();
            } finally {
                sftpCarrier.disconnect();
            }
            return fileList;
        }

    /**
     * 根据pid和日期查询抓包历史记录
     *
     * @param pid
     * @param datePath
     * @return
     */
    private SignalFileHistory queryHistoryOne(String pid, String datePath, int createHour) {
        SignalFileHistory signalFileHistory = new SignalFileHistory();
        signalFileHistory.setPid(pid);
        signalFileHistory.setCreateday(datePath);
        signalFileHistory.setCreatehour(createHour);
        List<SignalFileHistory> fileHistoryList = signalFileHistoryService.findList(signalFileHistory);
        if (fileHistoryList != null && fileHistoryList.size() > 0) {
            return fileHistoryList.get(0);
        }
        return null;
    }

    /**
     * 保存抓包历史
     *
     * @param pid
     * @param pcapPath
     * @param htmlPath
     * @param ebmHtmlPath
     * @param datePath
     */
    private void saveSignalFileHistory(String pid, String pcapPath, String htmlPath, String ebmHtmlPath, String datePath, int createHour, String capSize) {
        SignalFileHistory signalFileHistory = new SignalFileHistory();
        signalFileHistory.setPid(pid);
        signalFileHistory.setCappath(pcapPath);
        signalFileHistory.setHtmlpath(htmlPath);
        signalFileHistory.setEbmhtmlpath(ebmHtmlPath);
        signalFileHistory.setCreateday(datePath);
        signalFileHistory.setCreatehour(createHour);
        signalFileHistory.setCapsize(capSize);
        signalFileHistoryService.insert(signalFileHistory);
    }

    /**
     * 删除当前包所在目录下过期的抓包文件
     *
     * @param pcapPath
     */
    private static void deleteExpiredFiles(String pcapPath) {
        if (StringUtils.isNotBlank(pcapPath)) {
            File parentPath = new File(new File(pcapPath).getParent());
            if (parentPath.isDirectory()) {
                File[] files = parentPath.listFiles();
                for (File file : files) {
                    if (!matchPcapName(file.getName()) && !file.getName().endsWith(".html")) {
                        file.delete();
                    }
                }
            }
        }
    }

    /**
     * 执行脚本filter_genchart.pl，根据抓包文件生成流程图
     *
     * @param pcapName pcap包路径
     * @param msisdn   用户手机号
     * @param fileId   抓包号码对应的ID
     * @param datePath 抓包日期
     * @return 返回流程图路径
     */
    private String executeFlowChart(String pcapName, String msisdn, String fileId, String datePath,int hour, String opt) {

        String htmlPath = null;
        Process proc;
        String[] cmd = new String[3];
        cmd[0] = "sh";
        cmd[1] = "-c";
        cmd[2] = "/opt/Ericsson/core/bin/filter_genchart.pl " +
                " -hostfile /opt/Ericsson/core/bin/tracehosts -src " + pcapName + " -destpath /opt/Ericsson/core/signal/files/" + fileId + "/" + datePath + "/" + hour
                + " -msisdn " + msisdn;
        if (StringUtils.isNotBlank(opt)) {
            cmd[2] += " -tshark_opt '" + opt + "'";
        }
        log.info(cmd[2]);
        try {
            File file = new File("/opt/Ericsson/core/signal/files/" + fileId + "/" + datePath + "/" + hour);
            if (!file.exists()) {
                file.mkdirs();
            }
            proc = Runtime.getRuntime().exec(cmd);
            BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            StreamGobbler outputGobbler = new StreamGobbler(proc.getErrorStream(),"error",null);
            outputGobbler.start();
            String line;
            while ((line = br.readLine()) != null) {
                if (line.contains(".html")) {
                    htmlPath = line.trim();
                    log.info("chart：{" + htmlPath + "}");
                }
            }
            br.close();
            proc.waitFor();
            proc.destroy();
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }
        if (StringUtils.isNotBlank(htmlPath)) {
            return htmlPath;
        }
        return null;
    }

    private static boolean matchPcapName(String pcapName) {
        if (StringUtils.isNotBlank(pcapName)) {
            String pattern = "\\d{10,}-\\d+.pcap";
            Pattern r = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
            Matcher m = r.matcher(pcapName);
            return m.find();
        }
        return false;
    }
    @Data
    class SingleObject{
        private String imsi;
        private String dest;
    }
}
